<?php
/**
 * Lazy Collection For Eager Load / Safe Append
 *
 * Author: JennyWang
 * Date: 2018/4/11
 * Time: 21:27
 * Created by PhpStorm.
 */

namespace App\Services\Utils;

use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;

class PanxCollection extends EloquentCollection
{
    /**
     * @param $relations
     * @return $this
     */
    public function lazyLoad($relations): self
    {
        if ($this->isNotEmpty()) {
            if (is_string($relations)) {
                $relations = func_get_args();
            }

            /** @var Model $model */
            $model = $this->first();

            $loaded = $model->getRelations();
            $need_loads = array_diff($relations, array_keys($loaded));
            if (count($need_loads)) {
                $this->load($need_loads);
            };
        }

        return $this;
    }

    /**
     * @example
     *      new self([array_below])->eachExplodeCollapse(',')->all()
     *      ['1,2,3', '4', '5,6,7'] => ['1', '2', '3', '4', '5', '6', '7']
     *
     * @param $delimiter
     * @return Collection
     */
    public function eachExplodeCollapse(string $delimiter): Collection
    {
        return $this->map(function ($host) use ($delimiter) {
            return explode($delimiter, $host);
        })->collapse();
    }

    /**
     * @example
     *      请注意参数写 camelCase 和 snake_case 调用的方法都是 getCamelCaseAttribute 方法
     *      但返回前端的 key 是相应的 camelCase 或 snake_case
     *
     * @param array|string $attributes
     * @return $this
     */
    public function eachAppend($attributes): self
    {
        return $this->each(function (Model $model) use ($attributes) {
            return $model->append($attributes);
        });
    }

    /**
     * @return EloquentCollection
     */
    public function toEloquent(): EloquentCollection
    {
        return new EloquentCollection($this);
    }

    /**
     * @param callable $callback
     *
     * @return mixed
     */
    public function mapKeys(callable $callback): self
    {
        return $this->mapWithKeys(function ($val, $key) use ($callback) {
            return [$callback($key) => $val];
        });
    }
}